<template>
  <div class="goods-sku" v-for="item in goods.specs" :key="item.name">
    <dl>
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="v in item.values" :key="v.name">
          <img
            v-if="v.picture"
            :src="v.picture"
            :title="v.name"
            :alt="v.name"
            :class="{ selected: v.selected, disabled: v.disabled }"
            @click="changeStatus(item, v)"
          />
          <span
            v-else
            :class="{ selected: v.selected, disabled: v.disabled }"
            @click="changeStatus(item, v)"
            >{{ v.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>

<script>
// 导入幂集算法
import powerSet from '@/vender/power-set'
// 字典分隔符
const spliter = '★'

// 筛选
const getPathMap = (skus) => {
  // 字典
  const dict = {}
  // 遍历对象，取出数组
  skus.forEach((item) => {
    // 判断是否有库存
    if (item.inventory) {
      // 取出每项的valueName
      const valueNames = item.specs.map((v) => v.valueName)
      // 使用算法生成幂集结果
      const powerSetValue = powerSet(valueNames)
      // 遍历幂集结果转换为字符串字典
      powerSetValue.forEach((vv) => {
        // 转字符串
        const key = vv.join(spliter)
        // 判断有就追加，没有就添加
        if (!dict[key]) {
          // 添加
          dict[key] = [item.id]
        } else {
          // 追加
          dict[key].push(item.id)
        }
      })
    }
  })
  return dict
}

// 获取已选中的规格
const getSelectedArr = (specs) => {
  const arr = []
  specs.forEach((specs, index) => {
    // 遍历规格里的values的值找已选中的
    const obj = specs.values.find((v) => v.selected === true)
    // 将已选中的形成一个新的数组，有选中就写名字，否则写undefined
    arr[index] = obj ? obj.name : undefined
  })
  return arr
}

// ******更新按钮的状态
const updateDisabledStatus = (specs, dict) => {
  // 遍历规格
  specs.forEach((item, index) => {
    // 当前用户选中的规格
    const arr = getSelectedArr(specs)
    // 遍历规格下values数组
    item.values.forEach((v) => {
      // 判断已经被选中
      if (v.selected) return
      // 模拟用户选择
      arr[index] = v.name
      // 字典中查询
      const key = arr.filter((val) => val !== undefined).join(spliter)
      v.disabled = !dict[key]
    })
  })
}

// 默认选中状态  测试id：1369155864430120962
const initSelectedStatus = (goods, skuId) => {
  const obj = goods.skus.find(item => item.id === skuId)
  obj && obj.specs.forEach((item, index) => {
    const value = goods.specs[index].values.find(v => v.name === item.valueName)
    if (value) value.selected = true
  })
}

export default {
  name: 'GoodsSku',
  props: {
    goods: {
      type: Object,
      default: () => ({})
    },
    skuId: {
      type: String,
      default: ''
    }
  },
  emits: ['change'],
  setup (props, { emit }) {
    // 获取字典
    const dictionary = getPathMap(props.goods.skus)
    // 刚一进入页面的时候就先找字典里没有的规格
    updateDisabledStatus(props.goods.specs, dictionary)

    // 显示默认选中的数据，父传子
    initSelectedStatus(props.goods, props.skuId)

    const changeStatus = (theItem, theVal) => {
      // 禁用就不可以点击
      if (theVal.disabled) return
      // 判断当前点击属性的selected值是否为true
      if (theVal.selected) {
        theVal.selected = false
      } else {
        // 排他
        theItem.values.forEach((item) => {
          item.selected = false
        })
        theVal.selected = true
      }
      // 点击的时候也要找字典中没有的规格
      updateDisabledStatus(props.goods.specs, dictionary)

      // 规格 -- 子传父
      const selectArr = getSelectedArr(props.goods.specs).filter(v => v !== undefined)
      // 判断是否是完整的规格选中
      if (selectArr.length === props.goods.specs.length) {
        // 完整选中 拼接成字符串
        const key = selectArr.join(spliter)
        // 根据字符串获取id值
        const [skuId] = dictionary[key]
        // 根据id找到库存、新旧价格
        const { inventory, price, oldPrice, specs } = props.goods.skus.find(v => v.id === skuId)
        // 传给父组件
        emit('change', {
          skuId: skuId,
          inventory,
          price,
          oldPrice,
          attrsText: specs.map(v => `${v.name}:${v.valueName}`).join(' ')
        })
      } else {
        // 如果规格不完整
        emit('change', {})
      }
    }

    return { changeStatus }
  }
}
</script>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 10px;
  dl {
    display: flex;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      margin-bottom: 5px;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
